/*
    Linear Programming Library
    
    Created by Team Paragon (Shena Hoffmann, Arthur Powalka, Nasir Kenarangui)
    CSCE 689
    
    Simplex.h
    Header for the Simplex class. Contains declarations for the variables and functions used within Simplex.
    The Simplex class is used for performing operations (conversions, solving, etc.) related to the simplex linear programming algorithm.
*/


#ifndef Simplex_H   //ensure that Simplex is only included once
#define Simplex_H

#include <vector>
#include <iostream>
#include <algorithm>	//for find, min_element, for_each
#include <complex>
#include <iomanip>	//for setw
#include "LinProg.h"

using namespace std;

class Simplex : public LinProg
{
private:
    // ............ PRIVATE CLASS VARIABLES ............ //
    vector< complex<double> > complexObjective;	//algorithm needs the complex form of the original objectives
    complex<double> b0;		
    int row;
    int col;
    bool notFound=0; //indicates whether the pivot was found

    // ............ HELPER FUNCTIONS ............ //
    void findPivot(Simplex &data); //finds the pivot point for each iteration
    void basisExchange(Simplex &data);  //enters a new variable into the basis // essentially zero's out the other entries in the column of the pivot
    bool checkRealLessThanZero(Simplex &data);	//checks if the real part of objective is less than zero
    bool checkImagLessThanZero(Simplex &data); //checks if the imaginary part of the objective is less than zerp
    int indexOfLowestReal(Simplex&);		//finds a possible candidate for the entering variable //index of complexObjectives
    int indexOfLowestImag(Simplex&);		//find a possible candidate for the entering variable //index of complexObjectives
    bool allPositiveCoefficients(Simplex&);	//whether the coefficients of complex objective are all positive // not if imaginary part is positive then the entire number is positive
    void convertToIdentity(Simplex&);		//converts linear problem to have an identity
    
    struct realLess{				//comparison fucntion object
        bool operator()(complex<double> &val1, complex<double> &val2) const { return real(val1)<real(val2);} //const indicates it won't modify any private variables
    };

    struct imagLess{
        bool operator()(complex<double> &val1, complex<double> &val2) const { return imag(val1)<imag(val2);}
    };

    struct minPosComp{
        template<typename type>
        bool operator()(type &val1, type &val2) const
        { 
            if(real(val1)<0 && real(val2)>=0)
                return 0;
            if(real(val1)>=0 && real(val2)<0)
                return 1;
        return real(val1)<real(val2);
        }
    };
    vector< complex<double> > convertObjectiveToComplexForm(vector<double> oldObjective);
    vector<double> returnSolution(Simplex &data);
    
public:
    // ............ CONSTRUCTORS ............ //
    Simplex(); //creates an empty simplex object		
    Simplex(const LinProg &lp);
    Simplex(const Simplex &lp);
    Simplex(bool max, vector<double> objective, vector<vector<double>> constraints, vector<string> inequalitySigns, vector<double> inequalityVals, vector<bool> constrainedVars);
    
    // ............ DESTRUCTOR ............ //
    ~Simplex();
    
    // ............ CONVERSION FUNCTIONS ............ //
    Simplex convertToSimplexForm();
    Simplex testToSimplexForm();
    
    // ............ SOLVING FUNCTIONS ............ //
    tuple<vector<double>, string, double> solve();
    void setComplexObjective(vector< complex<double> > newObjective);

    // ............ PRINTING FUNCTIONS ............ //
    template<typename type>
    void printMatrix(vector< vector<type> > &matrix);

    template<typename type>
    void printVector(vector<type> vec);
    
    void printTableau(Simplex &data);
    void printProgram(Simplex);		
    
    // ............ OVERLOADED OPERATORS ............ //
    Simplex operator=(const Simplex &lp);
};
#endif
